/**
 * @Title: SingleThreadConnectionHolder.java
 * @Description:
 * @author zsw
 * <p>
 * Copyright(C) 2018-2019    NPlus
 * Company:   无锡核心信息科技有限公司
 * @version V2.0.0
 * @Date: 12:58 2020/4/2
 * <p>
 * 修改历史:
 * Date                 Author        Version        Description
 * -----------------------------------------------------------------------------------
 * 12:58 2020/4/2       zsw        2.0.0           初始化版本
 */
package com.example.dataTransaction;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * 第二步
 * ThreadLocal提供一个线程（Thread）局部变量，
 * 访问到某个变量的每一个线程都拥有自己的局部变量。
 * 说白了，
 * ThreadLocal就是想在多线程环境下去保证成员变量的安全。
 *
 * 如果把ThreadLocal置为null，那么意味着Heap中的ThreadLocal实例不在有强引用指向，只有弱引用存在，
 * 因此GC是可以回收这部分空间的，也就是key是可以回收的。但是value却存在一条从Current Thread过来的强引用链。
 * 因此只有当Current Thread销毁时，value才能得到释放。
 *
 * 因此，只要这个线程对象被gc回收，就不会出现内存泄露，
 * 但在threadLocal设为null和线程结束这段时间内不会被回收的，
 * 就发生了我们认为的内存泄露。
 * 最要命的是线程对象不被回收的情况，
 * 比如使用线程池的时候，线程结束是不会销毁的，再次使用的，就可能出现内存泄露。
 *
 * 在ThreadLocalMap中的set/getEntry方法中，
 * 会对key为null（也即是ThreadLocal为null）进行判断，
 * 如果为null的话，那么是会对value置为null的。我们也可以通过调用ThreadLocal的remove方法进行释放！
 */
public class SingleThreadConnectionHolder {
    private static ThreadLocal<ConnectionHolder> threadLocal = new ThreadLocal<>();

    private static ConnectionHolder getConnectionHolder() {
        ConnectionHolder connectionHolder = threadLocal.get();
        if (connectionHolder == null) {
            connectionHolder = new ConnectionHolder();
            threadLocal.set(connectionHolder);
        }
        return connectionHolder;
    }

    public static Connection getConnection(DataSource dataSource) throws SQLException {
        return getConnectionHolder().getConnectionByDataSource(dataSource);
    }

}
